package com.enation.app.javashop.core.promotion.luck.service.impl;

import com.alibaba.excel.EasyExcel;
import com.enation.app.javashop.core.aftersale.model.dos.RefundDO;
import com.enation.app.javashop.core.base.model.enums.YesNoEnum;
import com.enation.app.javashop.core.excel.ExceportLuckRecordVO;
import com.enation.app.javashop.core.member.model.dos.Member;
import com.enation.app.javashop.core.member.model.dos.MemberCoupon;
import com.enation.app.javashop.core.promotion.luck.model.dos.LuckDO;
import com.enation.app.javashop.core.promotion.luck.model.dos.LuckPrizeDO;
import com.enation.app.javashop.core.promotion.luck.model.dos.LuckRecordDO;
import com.enation.app.javashop.core.promotion.luck.model.enums.ExchangeTypeEnums;
import com.enation.app.javashop.core.promotion.luck.model.enums.PrizeTypeEnums;
import com.enation.app.javashop.core.promotion.luck.model.vo.LuckRecordCouponVO;
import com.enation.app.javashop.core.promotion.luck.model.vo.QueryLuckRecordVO;
import com.enation.app.javashop.core.promotion.luck.service.LuckRecordManager;
import com.enation.app.javashop.core.trade.order.model.enums.YesOrNoEnums;
import com.enation.app.javashop.framework.context.ThreadContextHolder;
import com.enation.app.javashop.framework.context.UserContext;
import com.enation.app.javashop.framework.database.DaoSupport;
import com.enation.app.javashop.framework.database.Page;
import com.enation.app.javashop.framework.exception.ServiceException;
import com.enation.app.javashop.framework.security.model.Seller;
import com.enation.app.javashop.framework.util.BeanUtil;
import com.enation.app.javashop.framework.util.DateUtil;
import com.enation.app.javashop.framework.util.SqlSplicingUtil;
import com.enation.app.javashop.framework.util.StringUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 孙建
 */
@Service
public class LuckRecordManagerImpl implements LuckRecordManager {

    @Autowired
    @Qualifier("tradeDaoSupport")
    private DaoSupport daoSupport;

    protected final Log logger = LogFactory.getLog(this.getClass());

    @Override
    public Page<LuckRecordDO> queryLuckRecordList(QueryLuckRecordVO queryLuckRecordVO) {
        // 1.组装查询条件参数
        StringBuilder sql = new StringBuilder("select * from es_luck_record");

        List<Object> termList = new ArrayList<>();
        List<String> sqlSplit = new ArrayList<>();

        sqlSplit.add(" is_delete=? ");
        termList.add(YesNoEnum.NO.getIndex());

        Integer sellerId = queryLuckRecordVO.getSellerId();
        if (sellerId != null) {
            sqlSplit.add(" seller_id=? ");
            termList.add(sellerId);
        }
        if (queryLuckRecordVO.getExchangeStatus() != null) {
            sqlSplit.add(" exchange_status=? ");
            termList.add(queryLuckRecordVO.getExchangeStatus());
        }
        if (queryLuckRecordVO.getExchangeType() != null) {
            sqlSplit.add(" exchange_type=? ");
            termList.add(queryLuckRecordVO.getExchangeType());
        }
        if (!StringUtil.isEmpty(queryLuckRecordVO.getPrizeName())) {
            sqlSplit.add(" prize_name like ? ");
            termList.add("%" + queryLuckRecordVO.getPrizeName() + "%");
        }
        if (queryLuckRecordVO.getLuckId() != null) {
            sqlSplit.add(" luck_id=? ");
            termList.add(queryLuckRecordVO.getLuckId());
        }
        if (queryLuckRecordVO.getMemberId() != null) {
            sqlSplit.add(" member_id=? ");
            termList.add(queryLuckRecordVO.getMemberId());
        }
        if (queryLuckRecordVO.getIsHit() != null) {
            sqlSplit.add(" is_hit=? ");
            termList.add(queryLuckRecordVO.getIsHit());
        }

        // 按时间查询
        Long startCreateTime = queryLuckRecordVO.getStartCreateTime();
        if (!ObjectUtils.isEmpty(startCreateTime)) {
            sqlSplit.add(" create_time >= ? ");
            termList.add(startCreateTime);
        }
        // Long endCreateTime = queryLuckRecordVO.getEndCreateTime();
        // if (!ObjectUtils.isEmpty(endCreateTime)) {
        //     sqlSplit.add(" create_time <= ? ");
        //     termList.add(endCreateTime);
        // }

        // 2.对sql条件语句进行拼接并查询
        String sqlSplicing = SqlSplicingUtil.sqlSplicing(sqlSplit);
        if (StringUtil.notEmpty(sqlSplicing)) {
            sql.append(sqlSplicing);
        }
        sql.append(" order by create_time desc");
        return this.daoSupport.queryForPage(sql.toString(), queryLuckRecordVO.getPageNo(), queryLuckRecordVO.getPageSize(),
                LuckRecordDO.class, termList.toArray());
    }


    @Override
    public LuckRecordDO saveLuckRecord(Member member, LuckDO luckDO, LuckPrizeDO luckPrize) {
        LuckRecordDO luckRecordDO = new LuckRecordDO();
        luckRecordDO.setLuckId(luckDO.getLuckId());
        luckRecordDO.setMemberId(member.getMemberId());
        luckRecordDO.setMemberFace(member.getFace());
        luckRecordDO.setMemberNickname(member.getNickname());
        luckRecordDO.setMemberRealName(member.getRealName());
        luckRecordDO.setLuckPrizeId(luckPrize.getLuckPrizeId());
        luckRecordDO.setPrizeName(luckPrize.getPrizeName());
        luckRecordDO.setPrizeType(luckPrize.getPrizeType());
        luckRecordDO.setPrizeImg(luckPrize.getPrizeImg());
        luckRecordDO.setWinPrizeNum(1);
        luckRecordDO.setIsHit(luckPrize.getPrizeType() != PrizeTypeEnums.THANKS.getIndex() ? 1 : 0);
        luckRecordDO.setDeliveryType(luckPrize.getDeliveryType());
        luckRecordDO.setSellerId(luckDO.getSellerId());
        luckRecordDO.setSellerName(luckDO.getSellerName());

        Integer prizeType = luckPrize.getPrizeType();
        if (prizeType == PrizeTypeEnums.ACTUAL.getIndex() || prizeType == PrizeTypeEnums.VIRTUAL.getIndex()) {
            luckRecordDO.setExchangeType(ExchangeTypeEnums.MANUAL.getIndex());
            luckRecordDO.setExchangeStatus(YesNoEnum.NO.getIndex());
        } else {
            luckRecordDO.setExchangeType(ExchangeTypeEnums.AUTO.getIndex());
            luckRecordDO.setExchangeStatus(YesNoEnum.YES.getIndex());
            luckRecordDO.setExchangeTime(DateUtil.getDateline());
        }
        luckRecordDO.setCreateTime(DateUtil.getDateline());
        luckRecordDO.setIsDelete(YesNoEnum.NO.getIndex());
        daoSupport.insert(luckRecordDO);
        return luckRecordDO;
    }

    /**
     * 抽奖记录导出
     */
    @Override
    public void luckRecordExport(QueryLuckRecordVO queryLuckRecordVO) {
        Page<LuckRecordDO> luckRecordDOPage = queryLuckRecordList(queryLuckRecordVO);
        List<LuckRecordDO> luckRecordDOList = luckRecordDOPage.getData();

        // 数据转换
        List<ExceportLuckRecordVO> exceportLuckRecordVOList = new ArrayList<>();
        for (LuckRecordDO luckRecordDO : luckRecordDOList) {
            ExceportLuckRecordVO exceportLuckRecordVO = new ExceportLuckRecordVO();
            BeanUtil.copyProperties(luckRecordDO, exceportLuckRecordVO);

            exceportLuckRecordVO.setCreateTime(DateUtil.toString(luckRecordDO.getCreateTime(), "yyyy-MM-dd HH:mm:ss"));
            exceportLuckRecordVO.setPrizeType(PrizeTypeEnums.getTextByIndex(luckRecordDO.getPrizeType()));
            exceportLuckRecordVO.setExchangeType(ExchangeTypeEnums.getTextByIndex(luckRecordDO.getExchangeType()));
            exceportLuckRecordVO.setExchangeStatus(YesNoEnum.getTextByIndex(luckRecordDO.getExchangeStatus()));
            if (luckRecordDO.getExchangeTime() != null) {
                exceportLuckRecordVO.setExchangeTime(DateUtil.toString(luckRecordDO.getExchangeTime(), "yyyy-MM-dd HH:mm:ss"));
            }

            exceportLuckRecordVOList.add(exceportLuckRecordVO);
        }

        HttpServletResponse response = getResponse("抽奖记录明细");

        // 输出
        try {
            EasyExcel.write(response.getOutputStream(), ExceportLuckRecordVO.class).sheet("抽奖记录明细").doWrite(exceportLuckRecordVOList);
        } catch (IOException e) {
            throw new ServiceException("500", "导出异常");
        }
    }

    // 兑换奖品
    @Override
    public void exchangePrize(String luckRecordIds) {
        if (StringUtil.isEmpty(luckRecordIds)) {
            return;
        }

        // 查询出相应的抽奖记录
        String querySql = "select * from es_luck_record where luck_record_id in ("+luckRecordIds+")";
        List<LuckRecordDO> luckRecordDOList = this.daoSupport.queryForList(querySql,LuckRecordDO.class);
        if (CollectionUtils.isEmpty(luckRecordDOList)) {
            return;
        }

        // 只有虚拟商品和实物商品可以手动修改兑奖状态
        Seller seller = UserContext.getSeller();
        List<Integer> prizeIds = new ArrayList<>();
        for (LuckRecordDO record : luckRecordDOList) {
            if (!record.getSellerId().equals(seller.getSellerId())) {
                throw new ServiceException("500", "没有权限操作非本店铺的兑奖记录！");
            }
            if (record.getPrizeType() == PrizeTypeEnums.ACTUAL.getIndex() || record.getPrizeType() == PrizeTypeEnums.VIRTUAL.getIndex()) {
                prizeIds.add(record.getLuckRecordId());
            }
        }

        if (CollectionUtils.isEmpty(prizeIds)) {
            return;
        }

        // 修改兑奖状态和兑奖时间
        String sql = "update es_luck_record set exchange_status = " + YesOrNoEnums.YES.getIndex() + ",exchange_time=" + DateUtil.getDateline() + " where luck_record_id in (" + StringUtil.listToString(prizeIds, ",") + ")";
        this.daoSupport.execute(sql);
    }

    // 订单退款之后需要退回抽奖奖品
    @Override
    public void LuckRefund(List<RefundDO> refundDO) {
        List<String> orderSnList = refundDO.stream().map(RefundDO::getOrderSn).distinct().collect(Collectors.toList());
        //  1、下单的时间段有抽奖活动，2、活动不是待上线状态，3、下单之后产生抽奖记录，且抽奖记录时间离下单时间最近的记录，4、中奖
        String snString="'"+StringUtil.listToString(orderSnList,"','")+"'";
        String luckRecordSql = "SELECT r.*,p.coupon_id FROM es_order o\n " +
                "LEFT JOIN es_luck l ON o.create_time  BETWEEN l.start_time AND l.end_time\n" +
                "LEFT JOIN es_luck_record r ON r.member_id=o.member_id\n" +
                "LEFT JOIN es_luck_prize p ON r.luck_prize_id=p.luck_prize_id \n" +
                "WHERE l.luck_id IS NOT NULL AND l.luck_status!=1 AND r.create_time > o.create_time   AND r.is_delete = 0 AND is_hit = 1 AND o.sn in ("+snString+") \n" +
                "GROUP BY o.sn ";

        List<LuckRecordCouponVO> recordDOList = this.daoSupport.queryForList(luckRecordSql, LuckRecordCouponVO.class);

        if (CollectionUtils.isEmpty(recordDOList)) {
            // 下单之后没有抽过奖，所以不需要退回
            logger.info("没有需要退回的奖品！");
            return;
        }

        // 1、回收优惠券
        List<LuckRecordCouponVO> couponRecordList = recordDOList.stream().filter(record -> !PrizeTypeEnums.COUPON.equals(record.getPrizeType())).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(couponRecordList)) {
            String couponSql = "update es_member_coupon set used_status = 2 WHERE coupon_id=? AND member_id=?";
            // 因为优惠券和用户ID必须是对应的关系，所以这个循环更新
            for (LuckRecordCouponVO luckRecordCouponVO : couponRecordList) {
                logger.info("收回优惠券：couponId="+luckRecordCouponVO.getCouponId()+"  memberId="+luckRecordCouponVO.getMemberId());
                this.daoSupport.execute(couponSql, luckRecordCouponVO.getCouponId(), luckRecordCouponVO.getMemberId());
            }
        }
        // 2、回收实物商品
        // if (PrizeTypeEnums.ACTUAL.equals(recordDO.getPrizeType())) {
        //
        // }
        // 3、回收虚拟商品
        // if (PrizeTypeEnums.VIRTUAL.equals(recordDO.getPrizeType())) {
        //
        // }


        // 删除抽奖记录
        this.deleteRecord(recordDOList.stream().map(LuckRecordCouponVO::getLuckRecordId).collect(Collectors.toList()));
    }

    private void deleteRecord(List<Integer> recordIds) {
        String luckRecordSql = "update es_luck_record set is_delete = ? where luck_record_id in (?)";
        this.daoSupport.execute(luckRecordSql, YesOrNoEnums.YES.getIndex(), StringUtil.listToString(recordIds,","));
    }

    private HttpServletResponse getResponse(String fileName) {
        HttpServletResponse response = ThreadContextHolder.getHttpResponse();
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
        return response;
    }

}
